package com.dcy.system.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.dcy.common.base.service.DcyBaseService;
import com.dcy.common.constant.Constant;
import com.dcy.common.utils.AdminLoginUtil;
import com.dcy.common.utils.TreeUtil;
import com.dcy.system.convert.ResourceConvert;
import com.dcy.system.dao.ResourceDao;
import com.dcy.system.enums.ResourceMenuCacheFlagEnum;
import com.dcy.system.enums.ResourceMenuExtFlagEnum;
import com.dcy.system.enums.ResourceMenuHiddenFlagEnum;
import com.dcy.system.enums.ResourcesTypeEnum;
import com.dcy.system.model.Resource;
import com.dcy.system.vo.in.ResourceCreateInVO;
import com.dcy.system.vo.in.ResourceUpdateInVO;
import com.dcy.system.vo.out.ResourceListOutVO;
import com.dcy.system.vo.out.RouterListOutVO;
import com.google.common.collect.ImmutableList;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 资源表 服务实现类
 * </p>
 *
 * @author dcy
 * @since 2020-08-19
 */
@RequiredArgsConstructor
@Service
public class ResourceService extends DcyBaseService {

    private final ResourceDao resourceDao;
    private final ResourceConvert resourceConvert = ResourceConvert.INSTANCE;

    /**
     * 获取tree-table 数据
     *
     * @return
     */
    public List<ResourceListOutVO> getResourceTreeList() {
        return resourceConvert.toOutList(TreeUtil.listToTree(resourceDao.list(new LambdaQueryWrapper<Resource>().orderByAsc(Resource::getResSort))));
    }

    /**
     * 获取菜单列表
     *
     * @return
     */
    public List<ResourceListOutVO> getMenuList() {
        List<Resource> resourcesList = resourceDao.list(new LambdaQueryWrapper<Resource>()
                .in(Resource::getType, Arrays.asList(ResourcesTypeEnum.CATALOGUE.getCode(), ResourcesTypeEnum.MENU.getCode()))
                .orderByAsc(Resource::getResSort));
        return resourceConvert.toOutList(TreeUtil.listToTree(resourcesList));
    }

    /**
     * 获取tree 数据
     *
     * @param roleId 角色id
     * @return
     */
    public List<String> getResourceIdListByRoleId(String roleId) {
        return resourceDao.getResourceIdListByRoleId(roleId);
    }

    /**
     * 保存
     *
     * @param resourceCreateInVO
     * @return
     */
    public Boolean save(ResourceCreateInVO resourceCreateInVO) {
        return resourceDao.save(resourceConvert.toResource(resourceCreateInVO));
    }

    /**
     * 删除
     *
     * @param id
     * @return
     */
    public Boolean delete(String id) {
        return resourceDao.removeById(id);
    }


    /**
     * 修改
     *
     * @param resourceUpdateInVO
     * @return
     */
    public Boolean update(ResourceUpdateInVO resourceUpdateInVO) {
        return resourceDao.updateById(resourceConvert.toResource(resourceUpdateInVO));
    }

    /**
     * 根据用户id 查询权限
     *
     * @return
     */
    public List<RouterListOutVO> getResourceList() {
        return generateRouter(TreeUtil.listToTree(resourceDao.selectAuthResourcesListByUserId(AdminLoginUtil.getUserId())));
    }

    private List<RouterListOutVO> generateRouter(List<Resource> resourcesList) {
        List<RouterListOutVO> routerListOutVOS = new ArrayList<>();
        resourcesList.forEach(resources -> {
            final List<Resource> children = resources.getChildren();
            RouterListOutVO routerListOutVO = new RouterListOutVO();
            routerListOutVO.setName(resources.getComponentName());
            routerListOutVO.setPath(resources.getRoutePath());
            routerListOutVO.setHidden(!ResourceMenuHiddenFlagEnum.getBoolByCode(resources.getMenuHiddenFlag()));
            // 设置元信息
            final RouterListOutVO.MetaOutputDTO metaOutputDTO = new RouterListOutVO.MetaOutputDTO();
            metaOutputDTO.setIcon(resources.getMenuIcon());
            metaOutputDTO.setTitle(resources.getTitle());
            metaOutputDTO.setNoCache(ResourceMenuCacheFlagEnum.NO.getCode().equals(resources.getMenuCacheFlag()));
            routerListOutVO.setMeta(metaOutputDTO);
            if (ResourceMenuExtFlagEnum.getByCode(resources.getMenuExtFlag()) == ResourceMenuExtFlagEnum.NO) {
                // 一级菜单
                if (Constant.COMMON_PARENT_ID.equals(resources.getParentId())) {
                    routerListOutVO.setComponent(StrUtil.isBlank(resources.getComponentPath()) ? Constant.ROUTER_LAYOUT : resources.getComponentPath());
                    // 如果不是一级菜单，并且菜单类型为目录，则代表是多级菜单
                } else if (ResourcesTypeEnum.CATALOGUE.getCode().equals(resources.getType())) {
                    routerListOutVO.setComponent(StrUtil.isBlank(resources.getComponentPath()) ? Constant.ROUTER_PARENT_VIEW : resources.getComponentPath());
                } else if (StrUtil.isNotBlank(resources.getComponentPath())) {
                    routerListOutVO.setComponent(resources.getComponentPath());
                }
            }
            if (CollUtil.isNotEmpty(children)) {
                routerListOutVO.setAlwaysShow(true);
                routerListOutVO.setRedirect(Constant.ROUTER_NO_REDIRECT);
                routerListOutVO.setChildren(generateRouter(children));
            } else if (Constant.COMMON_PARENT_ID.equals(resources.getParentId())) {
                // 当子集为空，并且是目录的时候，自动添加自己
                RouterListOutVO routerListOutVONew = new RouterListOutVO();
                routerListOutVONew.setMeta(routerListOutVO.getMeta());
                routerListOutVONew.setHidden(!ResourceMenuHiddenFlagEnum.getBoolByCode(resources.getMenuHiddenFlag()));
                // 不是外链
                if (ResourceMenuExtFlagEnum.getByCode(resources.getMenuExtFlag()) == ResourceMenuExtFlagEnum.NO) {
                    routerListOutVONew.setName(resources.getComponentName());
                    routerListOutVONew.setComponent(StrUtil.isBlank(resources.getComponentPath()) ? Constant.ROUTER_LAYOUT : resources.getComponentPath());
                }
                routerListOutVONew.setPath(resources.getRoutePath());
                routerListOutVO.setAlwaysShow(true);
                routerListOutVO.setComponent(Constant.ROUTER_LAYOUT);
                routerListOutVO.setChildren(ImmutableList.of(routerListOutVONew));
            }
            routerListOutVOS.add(routerListOutVO);
        });
        return routerListOutVOS;
    }
}
